/* Orbas:
 *     A open source CORBA Specification implementation from Huihoo.
 *
 * Copyright 2002-2003 Huihoo.org, Inc. All Right Reserved.
 *
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 *
 * For more information, visit:
 *
 * http://www.huihoo.org/orbas
 */



package org.huihoo.orbas.orb.protocols.iiop;

/**
 * <p>Description: </p>
 * UDP broadcaster in LAN.
 * <p>Copyright (c) 2002,2003</p>
 * <p>Company: <a href="http://www.huihoo.org/">huihoo.org</a></p>
 * @author <a href="http://www.huihoo.org/~mep">mep(mep@huihoo.com)</a>
 * @see <a href="http://www.huihoo.org/orbas">http://www.huihoo.org/orbas</a>
 * @version 1.0
 */

import com.cognition.util.j2me.io.Sender;
import org.huihoo.orbas.orb.ORB;
import org.huihoo.orbas.orb.protocols.ServerBroadcaster;
// import java.net.DatagramSocket;
// import java.net.DatagramPacket;
// import java.net.InetAddress;
//import java.net.SocketTimeoutException;
//import java.net.InetSocketAddress;
import java.io.IOException;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;

public class IiopBroadcaster
    implements ServerBroadcaster {

    ORB orb;
    java.util.Hashtable tables = new java.util.Hashtable();
    boolean flag;

    public IiopBroadcaster(ORB orb) {
        this.orb = orb;
        flag = true;
    }

    public void binding(String name,
                        org.omg.CORBA.Object obj) throws
        org.omg.CORBA.ORBPackage.InvalidName {

        String ref = null;

        try {
            ref = orb.object_to_string(obj);
        }
        catch (Exception e) {
        }

        tables.put(name, ref);
    }

    public void unbinding(String name) {
        tables.remove(name);
    }

    // TODO : document this function.
    /**
     * Resolves the binding of the given name somehow
     * @param name the IOR string to resolve the binding for.
     * @return a CORBA object if the binding could be resolved or null otherwise.
     */
    public org.omg.CORBA.Object resolveBinding(String name) {
        org.omg.CORBA.Object ret;

//    	System.out.println("resolveBinding " + name);
        //get the reference from network
        byte[] request = name.getBytes();
        try {
            // DatagramPacket packet =
            //    new DatagramPacket(request, request.length);

            // DatagramSocket sock = new DatagramSocket();

            //TODO: parameterize the server that we can broadcast to.
            //TODO: update the protocol so not just a name is sent.  Handle the security case.
            DatagramConnection dc = (DatagramConnection)Connector.open(
                    "datagram://localhost:" + Iiop.UDP_PORT);
            Sender sender = new Sender(dc);
            sender.send(null, request);

            // InetAddress destAddress = InetAddress.getLocalHost();
            // packet.setAddress(destAddress);
            // packet.setPort(Iiop.UDP_PORT);

            // sock.setBroadcast(true);
            // sock.send(packet);

            byte[] data = new byte[1500];
            Datagram dg = dc.newDatagram(data, data.length);

            dc.receive(dg);
            // Have we actually received something or
            // is this just a timeout ?
            if (dg.getLength() > 0) {
                System.out.println("Message received - "
                    + dg.getLength() + " bytes.");
            }

            /*
            DatagramPacket reply =
                new DatagramPacket(data, data.length);

            sock.setSoTimeout(3000);
            
            // This call will block until a datagram arrives
            try {
                sock.receive(reply);
            }
            catch (IOException e) {
            }
            
            String ior = new String(reply.getData(), 0, reply.getLength());
            */
            String ior = new String(dg.getData(), 0, dg.getLength());
            if (ior.startsWith("IOR:")) {
                return orb.string_to_object(ior);
            }
        } catch (ConnectionNotFoundException cnfe) {
            System.err.println("IiopBroadcaster: connection to localhost not found.");
            cnfe.printStackTrace();
        } catch (java.io.IOException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }

        return null;

    }

    public void run() {

        System.out.println("IiopBroadcaster: Broadcast thread started.");

        // DatagramSocket sock;

        try {
            DatagramConnection dc = (DatagramConnection)Connector.open(
                    "datagram://:" + Iiop.UDP_PORT);
            // sock = new DatagramSocket(Iiop.UDP_PORT);
            //sock.setReuseAddress(true);
            //sock.bind(new InetSocketAddress(Iiop.UDP_PORT));

            while (flag) {
                byte[] data = new byte[1500];
                Datagram packet = dc.newDatagram(data, data.length);
                // DatagramPacket packet =
                //    new DatagramPacket(data, data.length);

                // This call will block until a datagram arrives
//				System.out.println("Ready to resolve binding");
                //sock.receive(packet);
                dc.receive(packet);
                System.out.println("get resolve binding request");

                String message =
                    new String(packet.getData(), 0, packet.getLength());

				System.out.println("get resolve binding request " + message);

                //it is a server ior request
                //we create a reply
                String ret = (String) tables.get(message);
                if (ret == null) {
                    continue;
                }

                byte[] retData = ret.getBytes();

                Sender sender = new Sender(dc);
                sender.send(packet.getAddress(), retData);
                /*
                 DatagramPacket reply =
                    new DatagramPacket(retData,
                                       retData.length,
                                       packet.getAddress(),
                                       packet.getPort());

                //DatagramSocket replySock = new DatagramSocket(packet.getSocketAddress());
                //replySock.setBroadcast(true);
                sock.send(reply);
                */
            }
        }
        catch (java.io.IOException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
/*      catch (java.net.SocketException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
        catch (java.net.UnknownHostException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
*/
    }

    public void shutdown() {
        flag = false;
    }
}
